#include <qapplication.h>
#include <qdialog.h>
#include <qpushbutton.h>
#include <qstring.h>
#include <qdebug.h>
#include <QTime>
#include <QLabel>
#include <QMessageBox>

#include <QFile>


#include "SalesmanData.h"
#include "SalesmanChromosome.h"
#include "SalesmanEnvironment.h"

#include "TournamentSelectionStrategy.h"
//#include "RouletteWheelSelectionStrategy.h"
//#include "SimpleSelectionStrategy.h"

#include "SelectionStrategy.h"
#include "SelectionStrategyFactory.h"

#include "parameters.h"

#include "math.h"



int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    for(int i=0;i<argc;++i)
        qDebug() << argv[i];

    QString str = "";

    QString fileNameCity("greedy+ga7.xml");//("test.xml");

    SalesmanData salesman("./",fileNameCity);



    //salesman.saveToFile("./","test.xml");

    qDebug() << salesman;


    int popSize = 1000;//100;
    int selection = Tournament;
    bool adjustFit = false;
    double crossProb = 0.9;
    double mutProb = 0.05;
    int tournamentSize = 20;//10;
    bool replaceWorst = true;
    int addFresh = 4;
    int eliminateDuplicates = Replace;
    bool greedyStart = true;
    double bestFitness = 0;//-19.313709;
    int finishCond = GenerationCount;//BestFitnessKnown;//GenerationCount;

    int generationCount = 500;//100;
    int runNumber = 100;

    QString fileName = "salesman.txt";
    QFile* file = new QFile (fileName );

    if ( !file->open ( QIODevice::Append | QIODevice::Text ) )
        qFatal("cannot open file");

    QTextStream stream(file);

    stream << endl;
    stream << endl;

    stream << "popSize: " << popSize;
    stream << " selection: " << selection;
    stream << " adjustFit: " << adjustFit;
    stream << " crossProb: " << crossProb;
    stream << " mutProb: " << mutProb;
    stream << " tournamentSize: " << tournamentSize;
    stream << " replaceWorst: " << replaceWorst;
    stream << " addFresh: " << addFresh;
    stream << " eliminateDuplicates: " << eliminateDuplicates;
    stream << " bestFitness: " << bestFitness;
    stream << " runNumber: " << runNumber;
    stream << " generationCount: " << generationCount;
    stream << " greedyStart: " << greedyStart;
    stream << " finishCond: " << finishCond;
    stream << " fileName: " << fileNameCity;
    stream << endl;


    double sumOfBest = 0;
    int sumOfAge = 0;
    QList<int> ageList;
    QList<double> fitList;

    for(int i=0;i<runNumber;++i)
    {
        SelectionStrategy* selectionStrategy = SelectionStrategyFactory::getStrategy(selection);
        if(selection == Tournament)
            dynamic_cast<TournamentSelectionStrategy*>(selectionStrategy)->setSize(tournamentSize);

        SalesmanEnvironment salEnv(popSize, salesman, greedyStart);
        salEnv.setMaxGenerationsCount(100);
        salEnv.setSelectionStrategy(selectionStrategy);
        salEnv.setCrossoverProb(crossProb);
        salEnv.setMutationProb(mutProb);
        salEnv.setReplaceWorstRepresentative(replaceWorst);
        salEnv.setAddFreshChromosomes(addFresh);
        salEnv.setRemoveDuplicatesMethod(eliminateDuplicates);
        //if(bestFitness != 0)
        salEnv.setBestFitness(bestFitness);
        salEnv.setMaxGenerationsCount(generationCount);
        salEnv.setFinishConditionType(finishCond);
        salEnv.setAdjustFitness(adjustFit);
        salEnv.startSimulation();
        qDebug() << *salEnv.getSolution();

        str += salEnv.getStatisticsString();
        qDebug() << str;




        stream << QString::number(salEnv.getSolution()->getFitness(), 'f', 6) << "(";
        stream << salEnv.getAge() << ");";

        sumOfBest += salEnv.getSolution()->getFitness();
        sumOfAge += salEnv.getAge();

        ageList.append(salEnv.getAge());
        fitList.append(salEnv.getSolution()->getFitness());

        qDebug() << "run: " << runNumber;
        qDebug() << "i: " << i;

        sleep(1);//not working in windows
    }

    double average = sumOfAge/(double)runNumber;
    double averageFit = sumOfBest/(double)runNumber;

    //wariancja

    double sumSq = 0;
    for(int a=0;a<ageList.size();++a)
    {
        sumSq += (ageList.at(a) - average) * (ageList.at(a) - average);
    }
    double wariancja = sumSq/runNumber;
    double odchylenie = sqrt(wariancja);

    double sumSqFit = 0;
    for(int a=0;a<fitList.size();++a)
    {
        sumSqFit += (fitList.at(a) - averageFit) * (fitList.at(a) - averageFit);
    }
    double wariancjaFit = sumSqFit/runNumber;
    double odchylenieFit = sqrt(wariancjaFit);


    stream << endl;
    stream << "GEN av: " << average << " wariancja: " << wariancja << " odchylenie: " << odchylenie << endl;
    stream << "FIT av: " << averageFit << " wariancja: " << wariancjaFit << " odchylenie: " << odchylenieFit << endl;
    file->close ();


    //Brute Force search:
    //salEnv.findBestSalesmanRoute(salesman);



    //QMessageBox* messageBox = new QMessageBox();
    //messageBox->setText(str);
    //messageBox->show();

    return 0;//app.exec();
}



/* salesman.addCity("Barwinek", dist1);
 salesman.addCity("Bezledy", "706");
 salesman.addCity("Biała Podlaska", "386,38");
 salesman.addCity("Białystok", "521,224,154");
 salesman.addCity("Bielsko - Biała", "203,622,491,542");
 salesman.addCity("Bydgoszcz", "615,288,415,400,460");
 salesman.addCity("Chałupki", "361,651,544,572,113,443");
 salesman.addCity("Chełm", "333,495,127,281,408,489,477");
 salesman.addCity("Chyżne", "240,717,470,541,114,574,227,417");
 salesman.addCity("Ciechanów", "498,208,237,190,500,205,482,336,509");//2027
 salesman.addCity("Cieszyn", "283,741,496,562,35,479,78,443,149,472");//2027
 salesman.addCity("Częstochowa", "346,490,383,410,130,330,161,356,246,320,151");//2075
*/
/*salesman.addCity("Elbląg", "717,133,428,335,595,175,662,555,728,220,652,500");
 salesman.addCity("Gdańsk", "776,192,487,395,595,170,615,584,707,280,670,450,60");
 salesman.addCity("Gorzów Wielkopolski", "734,489,600,608,495,210,454,594,614,425,509,435,355,315");
 salesman.addCity("Gubin", "684,612,650,677,446,324,404,673,291,485,459,397,497,466,153");
 salesman.addCity("Hrebenne", "240,57,245,400,392,576,464,18,414,412,427,401,617,660,723,749");//2600???
 salesman.addCity("Jakuszyce", "617,671,655,655,363,398,305,633,454,598,301,324,546,594,281,231,709");
 salesman.addCity("Jelenia Góra", "593,647,631,630,340,375,281,609,430,575,277,300,520,570,255,207,685,24");
 salesman.addCity("Kalisz", "492,428,416,445,300,180,265,403,421,265,320,195,350,300,245,270,479,271,245");
 salesman.addCity("Katowice", "269,567,460,490,55,405,84,393,169,400,74,75,580,530,465,45,433,342,310,270");
 salesman.addCity("Kielce", "272,485,268,365,225,345,296,246,232,275,286,135,495,505,465,490,266,459,435,220,210");
 salesman.addCity("Kołbaskowo", "755,557,680,663,605,265,576,703,736,471,618,546,411,368,109,226,830,390,366,353,574,573");
 salesman.addCity("Konin", "518,371,364,390,340,120,322,428,453,205,358,209,295,245,235,286,486,328,375,55,285,260,345");
 salesman.addCity("Koszalin", "843,395,600,585,640,185,616,673,776,390,664,490,260,205,225,380,749,508,485,350,590,530,165,309");
 salesman.addCity("Kostrzyń", "866,462,639,656,543,173,430,706,657,466,485,484,329,360,47,101,762,201,277,291,485,511,125,275,274");
 salesman.addCity("Kraków", "197,621,374,445,85,477,156,321,96,415,122,150,630,610,585,535,306,414,390,340,70,135,694,355,660,605");
 salesman.addCity("Krosno", "34,664,359,495,250,585,362,299,340,470,283,385,690,680,735,685,249,612,590,465,270,245,859,445,815,748,200");
 salesman.addCity("Kudowa-Słone", "504,704,621,649,256,432,198,619,370,559,234,238,711,645,376,326,595,178,154,260,217,372,485,317,553,396,289,487");
 salesman.addCity("Kuźnica Białostocka", "579,282,212,58,708,456,301,339,599,250,620,469,395,454,666,735,458,746,722,502,546,425,721,450,641,713,503,552,707");
 salesman.addCity("Legnica", "538,580,576,610,300,375,258,554,414,445,313,250,455,505,215,167,630,91,65,190,270,370,326,240,420,237,340,540,159,667");
 salesman.addCity("Leszno", "561,480,505,510,325,205,281,528,437,345,336,275,355,405,210,145,604,191,165,125,290,345,330,140,310,241,369,560,235,599,100");
 salesman.addCity("Lublin", "265,437,121,295,340,420,409,68,349,280,375,290,485,515,580,605,144,565,510,335,330,180,686,369,605,618,255,240,551,314,485,460");
 salesman.addCity("Łomża", "520,206,210,75,540,315,523,323,550,120,513,360,260,320,545,605,409,651,625,380,440,320,491,329,510,584,455,595,600,135,570,445,265");
 salesman.addCity("Łódź", "410,364,297,215,260,205,287,330,369,180,277,129,375,340,345,389,396,379,355,120,205,135,453,110,450,383,275,405,344,283,295,245,250,275");
 salesman.addCity("Medyka", "177,713,345,484,352,604,421,218,387,505,387,396,706,765,743,752,132,679,655,499,337,261,852,520,785,782,265,143,554,542,606,629,228,483,398");
 salesman.addCity("Nowy Sącz", "96,662,406,510,150,520,265,353,147,455,187,250,675,680,650,588,346,514,490,415,175,175,646,455,765,658,100,95,390,599,440,465,285,485,315,240");
 salesman.addCity("Ogrodniki", "68,230,314,160,718,452,700,441,727,297,690,690,353,412,660,761,560,816,792,559,616,495,717,507,563,702,631,654,777,218,737,623,416,177,453,644,701");
 salesman.addCity("Olsztyn", "617,89,238,235,535,200,562,455,628,120,522,400,100,160,410,523,531,582,560,360,480,395,464,280,310,502,537,590,615,295,490,390,385,160,275,606,575,253");
 salesman.addCity("Olszyna", "390,609,662,716,458,336,416,685,572,497,391,457,509,487,186,61,729,174,150,282,427,502,295,298,413,118,466,664,284,747,125,157,585,617,395,731,567,773,535");
 salesman.addCity("Opole", "381,564,477,505,145,340,101,475,257,415,156,95,515,515,355,303,515,230,205,165,110,230,462,220,515,329,185,380,144,563,155,180,405,455,200,449,285,663,475,282");
 salesman.addCity("Ostrołęka", "512,179,203,113,514,290,496,316,523,84,486,335,225,284,509,569,402,612,588,346,412,291,555,294,475,548,427,485,573,171,533,433,258,36,253,476,468,213,125,581,429");
 salesman.addCity("Piła", "707,367,503,485,505,90,462,611,642,295,517,160,235,225,120,275,653,372,350,215,475,435,177,209,135,169,545,680,416,544,280,180,510,415,315,713,645,540,285,308,360,378");
 salesman.addCity("Piotrków Trybunalski", "364,409,297,330,215,275,242,275,324,240,232,80,280,410,370,398,351,258,335,130,160,90,481,155,435,380,237,335,319,388,280,255,205,280,45,353,270,458,310,378,175,254,340");
 salesman.addCity("Płock", "465,267,274,275,355,150,384,348,462,85,374,229,280,285,340,401,424,454,430,185,300,235,417,129,335,376,380,440,443,334,375,265,280,205,95,454,440,381,180,413,315,168,240,140");
 salesman.addCity("Poznań", "603,403,466,485,400,130,358,460,524,290,413,280,305,330,135,194,589,268,245,110,360,330,243,100,240,181,440,575,317,541,175,75,445,410,210,609,509,567,330,206,255,375,105,240,209");
 salesman.addCity("Przemyśl", "164,642,336,470,340,590,408,205,374,475,374,385,695,750,710,739,119,666,610,470,325,250,839,509,770,769,250,130,580,529,595,615,215,470,385,13,229,631,595,718,435,463,700,340,440,595");
 salesman.addCity("Radom", "205,411,94,295,295,315,370,172,306,205,332,185,420,450,475,501,248,461,435,230,260,75,584,269,500,514,210,270,447,351,380,355,105,245,150,284,250,421,310,481,305,217,445,105,170,340,270");
 salesman.addCity("Rzeszów", "90,609,296,430,255,525,234,243,267,410,290,315,625,685,645,701,150,582,560,400,240,180,755,440,705,689,170,65,496,489,510,525,175,430,320,97,160,591,525,634,350,423,615,275,375,510,85,205");
 salesman.addCity("Siedlce", "381,321,61,170,480,355,554,184,490,175,473,320,365,425,540,589,260,599,575,355,400,260,619,309,510,578,395,355,560,227,520,445,115,150,235,344,409,326,265,601,415,142,440,240,215,405,330,185,300");
 salesman.addCity("Sieradz", "439,430,363,390,245,215,234,350,361,300,266,115,385,335,295,523,426,309,285,55,190,165,406,90,400,336,255,410,270,449,230,180,280,340,65,428,345,519,340,329,135,319,265,75,169,165,415,180,350,370");
 salesman.addCity("Skierniewice", "409,359,242,270,300,240,331,276,413,175,322,170,365,365,380,448,362,447,425,180,245,165,497,145,415,420,320,380,436,328,370,305,220,220,60,398,369,398,270,457,265,194,320,90,90,245,385,115,320,180,125");
 salesman.addCity("Słupsk", "823,326,587,525,660,200,653,661,800,360,723,570,195,135,295,470,727,546,520,380,650,580,234,320,70,283,720,795,595,581,455,355,595,445,405,821,770,546,295,482,535,410,175,490,355,280,810,530,735,525,415,435");
 salesman.addCity("Suwałki", "677,186,270,116,674,408,656,397,683,253,646,646,309,368,616,717,516,772,748,515,572,451,673,463,519,663,587,610,736,122,693,579,372,133,409,600,657,44,209,729,589,169,496,414,337,523,587,377,547,282,475,354,502");
 salesman.addCity("Szczecin", "737,539,675,660,600,260,558,698,714,465,613,550,405,365,105,164,825,385,360,350,570,569,18,340,160,120,690,740,480,716,320,325,680,485,450,847,641,712,460,290,455,550,170,475,410,240,835,580,750,615,400,490,230,668");
 salesman.addCity("Świecko", "710,683,649,656,472,304,430,725,586,474,485,464,464,407,94,59,779,242,226,296,441,513,203,285,321,44,561,711,352,714,193,171,657,594,393,778,614,756,497,113,329,558,216,450,390,183,765,553,724,588,320,430,351,712,198");
 salesman.addCity("Świnoujście", "938,546,675,710,728,312,641,835,797,518,696,631,441,354,200,317,877,481,457,438,378,359,114,378,151,216,798,903,576,768,417,421,733,538,538,937,842,733,467,386,553,602,224,566,464,328,924,658,840,666,491,544,233,689,109,296");
 salesman.addCity("Tarnobrzeg", "166,540,225,390,233,449,239,202,242,332,268,241,551,610,570,596,160,565,541,326,218,106,679,365,630,609,146,139,435,448,492,451,134,389,243,173,151,550,451,591,335,346,540,198,299,436,142,129,76,250,273,243,687,506,674,619,764");
 salesman.addCity("Tarnów", "155,603,347,480,170,460,249,294,179,395,205,237,615,620,580,570,235,497,475,340,155,120,729,375,615,621,85,150,372,540,425,445,225,435,255,182,59,642,515,549,265,409,550,210,350,450,170,190,85,340,285,300,700,598,729,596,763,92");
 salesman.addCity("Terespol", "425,421,39,193,530,454,583,166,509,276,535,422,467,526,639,689,284,694,670,455,499,307,719,403,639,514,413,398,663,251,620,544,160,249,336,388,445,353,367,701,516,242,542,336,313,505,375,233,335,100,402,281,626,309,714,688,766,264,386");
 salesman.addCity("Toruń", "511,256,369,350,420,45,447,443,570,160,437,320,180,180,255,341,530,415,370,170,365,295,311,115,230,303,480,540,436,410,325,255,375,280,160,554,415,420,165,353,335,244,135,195,109,145,540,270,475,310,205,185,245,376,309,330,358,403,415,408");
 salesman.addCity("Wałbrzych", "548,632,572,605,280,340,222,550,405,515,277,240,540,570,280,231,642,83,60,190,260,375,390,245,480,301,337,530,95,663,65,165,480,570,295,596,440,733,515,189,145,529,345,275,370,240,585,380,500,515,225,365,520,689,385,257,481,482,415,611,360");
 salesman.addCity("Warszawa", "398,308,162,190,400,255,382,236,415,100,372,220,320,341,440,488,312,498,475,255,300,175,518,200,395,477,315,370,487,248,420,345,170,140,135,405,355,318,220,500,315,114,340,140,110,305,375,105,310,100,200,80,425,274,515,487,565,232,295,201,205,415");
 salesman.addCity("Włocławek", "453,314,322,315,360,105,389,396,512,130,379,380,235,235,295,535,472,405,380,130,305,240,369,75,290,332,420,480,394,382,315,215,330,250,100,496,355,429,215,365,295,216,190,145,50,160,485,210,415,260,145,130,305,385,369,342,416,345,355,361,60,310,160");
 salesman.addCity("Wrocław", "466,564,504,535,230,275,86,482,342,445,241,180,470,485,270,218,558,151,125,120,195,300,377,175,415,288,270,465,140,595,70,95,415,500,225,534,370,738,475,197,85,461,275,205,309,170,520,310,435,450,160,295,450,621,370,244,468,420,350,543,290,70,345,290");
 salesman.addCity("Zakopane", "194,728,481,636,129,584,242,424,49,520,164,239,739,691,625,560,443,477,453,407,162,243,719,446,761,630,107,195,379,694,571,454,360,561,365,338,98,738,639,696,274,53,635,335,477,517,325,317,242,501,354,409,809,394,714,586,827,253,152,523,510,394,420,453,342");
 salesman.addCity("Zamość", "267,522,186,340,385,517,454,59,394,363,420,369,558,601,664,690,59,646,622,420,370,258,771,448,690,703,398,240,631,398,567,545,85,350,337,159,303,501,472,696,487,343,594,292,365,530,146,189,177,201,367,303,678,457,766,716,818,152,244,225,471,563,253,413,499,401");
 salesman.addCity("Zgorzelec", "627,654,665,698,389,366,347,643,503,523,402,340,539,529,226,145,748,82,66,281,358,460,325,330,473,158,430,627,220,746,89,187,575,651,385,695,531,816,565,84,246,611,338,368,443,236,682,471,598,609,319,457,512,759,320,160,416,581,513,695,383,147,508,387,161,503,660");
 salesman.addCity("Zielona Góra", "615,550,588,615,385,260,342,611,498,425,397,335,435,425,110,62,687,169,145,210,355,430,221,229,340,132,475,325,264,673,105,85,545,545,325,690,529,699,460,74,240,507,235,335,340,130,675,440,640,525,260,385,410,655,215,88,312,534,508,627,279,170,425,290,155,498,628,104");//best 7199
*/

 /*salesman.addCity( SalesmanCity("A", QPointF(0,2)) );
 salesman.addCity( SalesmanCity("B", QPointF(0,3)) );
 salesman.addCity( SalesmanCity("C", QPointF(0,4)) );
 salesman.addCity( SalesmanCity("D", QPointF(1,5)) );
 salesman.addCity( SalesmanCity("E", QPointF(2,6)) );
 salesman.addCity( SalesmanCity("F", QPointF(3,6)) );
 salesman.addCity( SalesmanCity("G", QPointF(4,6)) );
 salesman.addCity( SalesmanCity("H", QPointF(5,5)) );
 salesman.addCity( SalesmanCity("I", QPointF(6,4)) );
 salesman.addCity( SalesmanCity("J", QPointF(6,3)) );
 salesman.addCity( SalesmanCity("K", QPointF(6,2)) );
 salesman.addCity( SalesmanCity("L", QPointF(5,1)) );
 salesman.addCity( SalesmanCity("M", QPointF(4,0)) );
 salesman.addCity( SalesmanCity("N", QPointF(3,0)) );
 salesman.addCity( SalesmanCity("O", QPointF(2,0)) );
 salesman.addCity( SalesmanCity("P", QPointF(1,1)) );*/

